package aaa.screen;

import greendroid.app.GDActivity;
import greendroid.widget.ActionBarItem;
import greendroid.widget.ActionBarItem.Type;

import java.text.SimpleDateFormat;
import java.util.Date;

import aaa.database.Database;
import aaa.exception.AAAException;
import aaa.main.R;
import aaa.schedule.Schedule;
import aaa.schedule.UpdateListener;
import aaa.schedule.parameters.ParameterType;
import aaa.schedule.parameters.Parameters;
import aaa.schedule.parameters.ScheduleName;
import aaa.schedule.parameters.SchedulePeriod;
import aaa.schedule.parameters.ScheduleProjectId;
import aaa.schedule.parameters.ScheduleResource;
import aaa.schedule.parameters.ScheduleRessourceTitle;
import aaa.update.UpdateManager;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

/**
 * View displaying the form for creating a new schedule.
 * 
 * @author		Schnell Michaël, Zanette Sébastien
 */
public class CreateScheduleScreen extends GDActivity implements UpdateListener {

	/**
	 * Id of the settings item in the action bar.
	 */
	private static final int ITEM_SETTINGS = 0 ;

	/**
	 * Id of the help item in the action bar.
	 */
	private static final int ITEM_HELP     = 1 ;

	/**
	 * Component containing the different fields from the form.
	 */
	private LinearLayout fields ;

	/**
	 * Different fields displayed in the form.
	 */
	protected Parameters params ;

	/**
	 * Insertion index for the new ressources.
	 */
	private int newResIndex ;

	/** 
	 * Initializes this view.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		this.onCreate(savedInstanceState, "Ajout d'un emploi du temps") ;
	}// onCreate(Bundle)

	/**
	 * Initializes this view with the given title.
	 * 
	 * @param 	savedInstanceState
	 * 			If the activity is being re-initialized after previously being shut 
	 * 			down then this {@code Bundle} contains the data it most recently supplied
	 * 			in onSaveInstanceState(Bundle). Note: Otherwise it is null.
	 * 
	 * @param 	title
	 * 			title used for this view
	 */
	public void onCreate(Bundle savedInstanceState, String title) {
		super.onCreate(savedInstanceState) ;
		this.setTitle(title) ;
		this.initActionBar() ;
		this.init() ;
		this.initListeners();
	}// onCreate(Bundle, String)

//	/**
//	 * Adds this view to the listener list of the {@code UpdateManager}.
//	 */
//	@Override
//	protected void onStart() {
//		super.onStart() ;
//		UpdateManager.getInstance().addListener(this) ;
//	}// onStart()

//	/**
//	 * Removes this view from the listener list of the {@code UpdateManager}.
//	 */
//	@Override
//	protected void onStop() {
//		super.onStop() ;
//		UpdateManager.getInstance().removeListener(this) ;		
//	}// onStop()

	/**
	 * Initializes the action bar of this view.
	 */
	private void initActionBar() {
		this.addActionBarItem(Type.Settings, ITEM_SETTINGS) ;
		this.addActionBarItem(Type.Help, ITEM_HELP) ;
	}// initActionBar()

	/**
	 * Handles the clicks on the action bar items.
	 */
	@Override
	public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
		switch (item.getItemId()) {
		case CreateScheduleScreen.ITEM_SETTINGS :
			//TODO A implementer
			Toast.makeText(this, 
					"Cette opération n'est pas encore supportée.", 
					Toast.LENGTH_SHORT).show() ;
			break ;

		case CreateScheduleScreen.ITEM_HELP :
			this.startActivity(new Intent(this, InfoTabActivity.class)) ;
			break ;

		default :
			return super.onHandleActionBarItemClick(item, position) ;
		}// switch

		return true ;
	}// onHandleActionBarItemClick(ActionBarItem, int)

	/**
	 * Initializes the fields list with the given values as well as
	 * the graphical output (view).
	 * 
	 * @param 	name
	 * 			Initial values for the schedule name
	 * 
	 * @param 	resources
	 * 			Initial values for the resources
	 * 
	 * @param 	period
	 * 			Initial value for the period
	 * 
	 * @param 	projectId
	 * 			Initial value for the selected project
	 */
	public void init(String name, String resources, String period, String projectId) {
		LayoutInflater inflater = LayoutInflater.from(this) ;

		// Initialzing the fields --------------------------------------------------
		this.params = new Parameters() ;
		this.params.add(new ScheduleName(inflater,name));
		this.params.add(new ScheduleRessourceTitle(inflater, this));
		this.newResIndex = 2 ;
		for(String ressource : resources.split(",")) {
			this.params.add(new ScheduleResource(inflater, ressource, this)) ;
			this.newResIndex++ ;
		}// for
		this.params.add(new SchedulePeriod(inflater, period));
		this.params.add(new ScheduleProjectId(inflater, projectId));

		// Building the view layout ------------------------------------------------
		LinearLayout ll = (LinearLayout) View.inflate(this, 
				R.layout.create_schedule_screen, null) ;
		this.fields = (LinearLayout) ll.findViewById(R.id.fields) ;
		this.fields.setOrientation(LinearLayout.VERTICAL) ;
		for(ParameterType param : this.params) {
			this.fields.addView(param.getView(null, null)) ;
		}// for

		this.setActionBarContentView(ll) ;
	}// init(String, String, String, String)

	/**
	 * Adds a new resource to this view.
	 */
	public void addResource () {
		LayoutInflater inflater = LayoutInflater.from(this) ;
		ParameterType newRes = new ScheduleResource(inflater, "", this) ;
		this.params.add(this.newResIndex, newRes) ;
		this.fields.addView(newRes.getView(null,  null), this.newResIndex) ;
		this.newResIndex++ ;
	}// addResource()

	/**
	 * Removes a resource from this view.
	 * 
	 * @param 	removedView
	 * 			view which should well be removed
	 * 
	 * @param 	id
	 * 			id of the view which should be removed
	 * 
	 * @see		ScheduleResource
	 */
	public void removeResource (View removedView, int id) {
		this.fields.removeView(removedView) ;
		this.params.removeResource(id) ;
		this.newResIndex-- ;
	}// removeResource()

	/**
	 * Initializes this view with default values.
	 */
	public void init() {
		this.init("", "", "", "") ;
	}// init()

	/**
	 * Attaches the listeners to the save and cancel buttons.
	 */
	protected void initListeners() {	
		final Button saveButton   = (Button) this.findViewById(R.id.saveSchedule) ;
		final Button boutonCancel = (Button) this.findViewById(R.id.cancelSchedule) ;
		saveButton.setOnClickListener(this.getSaveListener()) ;
		boutonCancel.setOnClickListener(new CancelListener(this)) ;
	}// initListeners()

	/**
	 * Returns the first instance of {@code ParamaterType} found with the given id.
	 * 
	 * @param 	id
	 * 			id of the search {@code ParameterType}
	 * 
	 * @return	First instance of {@code ParamaterType} found with the given id
	 */
	public ParameterType getById(String id) {
		return this.params.getById(id) ;
	}// getById(String)

	/**
	 * Returns all the instances of {@code ParamaterType} found with the given id.
	 * 
	 * @param 	id
	 * 			id of the search {@code ParameterType}
	 * 
	 * @return	Array containing all the instance of {@code ParamaterType} found 
	 * 			with the given id
	 */
	public Parameters getAllById(String id) {
		return this.params.getAllById(id) ;
	}// getAllById(String)

	/**
	 * Returns the graphical component containing the form fields.
	 * 
	 * @return	
	 */
	public LinearLayout getFields() {
		return this.fields ;
	}// getFields()

	/**
	 * OnClickListener for the save button.
	 * 
	 * <p>Retrives the data from the form and inserts the schedule into the database
	 * if possible.
	 * 
	 * @author 	Schnell Michaël
	 */
	class SaveListener extends Object implements OnClickListener {

		/**
		 * View containing the component attached to this listener.
		 */
		protected CreateScheduleScreen container ;

		/**
		 * Sole constructor. 
		 * 
		 * @param 	container
		 * 			View containing the component attached to this listener
		 */
		public SaveListener(CreateScheduleScreen container) {
			super() ;
			this.container = container ;
		}// SaveListener(CreateScheduleScreen)

		/**
		 * Handles the click on the attached component.
		 * 
		 * @param	actualView
		 * 			view of the component who has received a click event
		 */
		public void onClick(View actualView) {
			// Retrieve form data
			String name       = this.container.getById(ScheduleName.FIELD_ID).getValue(this.container.getFields()).toString() ;
			String ressources = this.container.getScheduleResources() ;
			int period        = (Integer) this.container.getById(SchedulePeriod.FIELD_ID).getValue(this.container.getFields()) ;
			int projectId     = (Integer) this.container.getById(ScheduleProjectId.FIELD_ID).getValue(this.container.getFields()) ;
			String lastModif  = "null" ;
			int notify        = 1 ;
			String created    = new SimpleDateFormat("yyyy/MM/dd HH:mm").format(new Date()) ;

			// Data testing and schedule creation
			Schedule s = new Schedule(projectId, name, ressources, period, lastModif, notify, created) ;
			Database db = new Database(this.container) ;
			try {
				s.validate(db) ;
				db.insertSchedule(s) ;
				Intent intent = new Intent(this.container, UpdateManager.class) ;
				intent.putExtra("aaa.schedule.name", name) ;
				this.container.startService(intent) ;
				//UpdateManager.getInstance().addQueue(s.getName()) ;
				this.container.onBackPressed() ;
			} catch (AAAException e) {
				Toast.makeText(this.container, e.getMessage(), Toast.LENGTH_LONG).show() ;
			}// try
		}// onClick(View) 

	}// class SaveListener

	/**
	 * OnClickListener for the cancel button.
	 * 
	 * <p>Returns to the previous view.
	 * 
	 * @author 	Schnell Michaël
	 */
	class CancelListener implements OnClickListener {

		/**
		 * View containing the component attached to this listener.
		 */
		protected CreateScheduleScreen container ;

		/**
		 * Sole constructor. 
		 * 
		 * @param 	container
		 * 			View containing the component attached to this listener
		 */
		public CancelListener(CreateScheduleScreen container) {
			super() ;
			this.container = container ;
		}// CancelListener(CreateScheduleScreen)

		/**
		 * Handles the click on the attached component.
		 * 
		 * @param	actualView
		 * 			view of the component who has received a click event
		 */
		public void onClick(View actuelView) {
			this.container.onBackPressed() ;
		}// onClick(View)
		
	}// class CancelListener

	/**
	 * Returns an instance of an {@code OnClickListener} for the save action.
	 * 
	 * @return	instance of an {@code OnClickListener} for the save action
	 */
	protected OnClickListener getSaveListener() {
		return new SaveListener(this) ;
	}// getSaveListener()

	/**
	 * Used to display error messages if a schedule could not be updated.
	 */
	public void onUpdate(Object... args) {
		if ((args.length >= 3) && (args[2] instanceof AAAException)) {
			AAAException ex = (AAAException) args[2] ;
			Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG) ;
		}// if
	}// onUpdate(Object...)
	
	protected String getScheduleResources () {
		StringBuffer resString = new StringBuffer() ;
		for(int resId=2; resId < this.newResIndex; ++resId) {
			View resView = this.fields.getChildAt(resId) ;
			String value = (String) this.params.get(resId).getValue(resView) ;
			if (value.length() > 0) {
				resString.append(",") ;
				resString.append(value) ;
			}// if
		}// for
		if (resString.length() == 0) {
			return "" ;
		}// if
		return resString.substring(1) ;
	}// getResources()

}// class CreateScheduleScreen